
package com.insigma.business.qrcode.common.template.area;

import com.insigma.business.qrcode.common.dto.ErrorCodeEnum;
import com.insigma.business.qrcode.common.util.*;
import com.insigma.business.qrcode.common.vo.BaseResponse;
import com.insigma.business.qrcode.common.vo.RestfulResult;
import com.insigma.business.qrcode.welfare.dto.ApplicationErrorTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;


@Component
public class ServiceTemplate {


    private static final Logger logger = LoggerFactory.getLogger(
            ServiceTemplate.class);


    public void execute(final BaseResponse baseResponse, final ServiceCallback action) {


        try {
             /*Profiler.start();
            Profiler.enter("执行逻辑");*/


            action.check();


            action.executeService();


            setupSuccessResult(baseResponse,action.getScenarioEnum(),false);
        } catch (BizException be){
            if (be.getErrorCodeEnum() != ErrorCodeEnum.ERROR_IDEMPOTENCY) {
                ExceptionUtil.caught(logger,be,action.getScenarioEnum(),"|执行业务处理失败");
                setupFailedResult(baseResponse,action.getScenarioEnum(),be,be.getMessage());
            } else {
                LogUtil.warn(logger,"服务出现业务幂等|信息:" , be);
                setupSuccessResult(baseResponse,action.getScenarioEnum(),true);
            }
        }catch (Throwable e) {
            ExceptionUtil.caught(logger,e,action.getScenarioEnum(),"|执行业务处理失败");
            setupFailedResult(baseResponse,action.getScenarioEnum(),null, e.getMessage());
        }  finally {
            /*Profiler.release();

            Profiler.reset();*/

            /*if(baseResponse instanceof BasePagingResponse){

            }else {

            }*/
        }
    }

    public void execute(final RestfulResult baseResponse, final ServiceCallback action) {


        try {
             /*Profiler.start();
            Profiler.enter("执行逻辑");*/


            action.check();


            action.executeService();


            setResult(baseResponse,action.getScenarioEnum(),false);
        } catch (BizException be){
            if (be.getErrorCodeEnum() != ErrorCodeEnum.ERROR_IDEMPOTENCY) {
                ExceptionUtil.caught(logger,be,action.getScenarioEnum(),"|执行业务处理失败");
                setupFailedResult(baseResponse,action.getScenarioEnum(),be,be.getMessage());
            } else {
                LogUtil.warn(logger,"服务出现业务幂等|信息:" , be);
                setupSuccessResult(baseResponse,action.getScenarioEnum(),true);
            }
        }catch (Throwable e) {
            ExceptionUtil.caught(logger,e,action.getScenarioEnum(),"|执行业务处理失败");
            setupFailedResult(baseResponse,action.getScenarioEnum(),null, e.getMessage());
        }  finally {
            /*Profiler.release();

            Profiler.reset();*/

            /*if(baseResponse instanceof BasePagingResponse){

            }else {

            }*/
        }
    }

    public void execute(final ServiceCallback action) {
        try {
            action.check();
            action.executeService();
        } catch (BizException be){
            if (be.getErrorCodeEnum() != ErrorCodeEnum.ERROR_IDEMPOTENCY) {
                ExceptionUtil.caught(logger,be,action.getScenarioEnum(),"|执行业务处理失败");
            } else {
                LogUtil.warn(logger,"服务出现业务幂等|信息:" , be);
            }
        }catch (Throwable e) {
            ExceptionUtil.caught(logger,e,action.getScenarioEnum(),"|执行业务处理失败");
        }
    }


    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void execute(final TransactionTemplate transactionTemplate,
                        final BaseResponse baseResponse, final ServiceCallback action) {



        transactionTemplate.execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                try {
                     /*Profiler.start();
                    Profiler.enter("执行逻辑");*/


                    action.check();


                    action.executeService();


                    setupSuccessResult(baseResponse, action.getScenarioEnum(),false);
                } catch (BizException be){
                    status.setRollbackOnly();
                    if (be.getErrorCodeEnum() != ErrorCodeEnum.ERROR_IDEMPOTENCY) {
                        ExceptionUtil.caught(logger,be,action.getScenarioEnum(),"|执行业务处理失败");
                        setupFailedResult(baseResponse,action.getScenarioEnum(),be,be.getMessage());
                    } else {
                        LogUtil.warn(logger,"服务出现业务幂等|信息：" , be);
                        setupSuccessResult(baseResponse,action.getScenarioEnum(),true);
                    }
                } catch (Throwable e) {
                    status.setRollbackOnly();
                    ExceptionUtil.caught(logger,e,action.getScenarioEnum(),"|执行业务处理失败");
                    setupFailedResult(baseResponse,action.getScenarioEnum(),null, e.getMessage());
                }  finally {
                    /*Profiler.release();

                    Profiler.reset();*/

                }

                return baseResponse;
            }
        });
    }

//    public void executeCustom(final RestfulResult restfulResult, final ServiceCallback action) {
//        try {
//
//            action.check();
//
//
//            action.executeService();
//        } catch (AccessFailedException afe) {
//            ExceptionUtil.caught(logger, afe, action.getOperation(), "|执行业务处理失败");
//            setupFailedResult(restfulResult, afe.getErrCode(),afe.getErrMsg(), null);
//        } catch (BizException be) {
//            ExceptionUtil.caught(logger, be, action.getOperation(), "|执行业务处理失败");
//            setupFailedResult(restfulResult, be.getErrorCodeEnum().getCode(),(StringUtils.isNotBlank(be.getMessage())?be.getMessage():be.getErrorCodeEnum().getDesc()), null);
//        } catch (Exception e) {
//            ExceptionUtil.caught(logger, e, action.getOperation(), "|执行业务处理失败");
//            RestfulResultUtil.setupFailed(restfulResult, ConsumerCodeEnum.INTERNAL_ERROR.getCode(), "服务器在偷懒,请迅速举报给客服");
//        }
//    }

    private void setupSuccessResult(final BaseResponse baseResponse,final ScenarioCodeEnum scenarioCodeEnum, final boolean isIdempotent){
        baseResponse.setSuccess(true);

        if(isIdempotent){
            final ErrorContext errorContext = new ErrorContext(
                    CommonConstant.PRODUCTION_AND_APP_CODE , scenarioCodeEnum.getCode(), ApplicationErrorTypeEnum.BIZ_INVALID_ERROR.getCode() + ErrorCodeEnum.ERROR_IDEMPOTENCY.getCode(),ErrorCodeEnum.ERROR_IDEMPOTENCY.getDesc());
            baseResponse.setErrorCtx(errorContext);
        }
    }

    private void setupSuccessResult(final RestfulResult baseResponse,final ScenarioCodeEnum scenarioCodeEnum, final boolean isIdempotent){
        baseResponse.setSuccess(true);

        if(isIdempotent){
            final ErrorContext errorContext = new ErrorContext(
                    CommonConstant.PRODUCTION_AND_APP_CODE , scenarioCodeEnum.getCode(), ApplicationErrorTypeEnum.BIZ_INVALID_ERROR.getCode() + ErrorCodeEnum.ERROR_IDEMPOTENCY.getCode(),ErrorCodeEnum.ERROR_IDEMPOTENCY.getDesc());
            baseResponse.setErrorCtx(errorContext);
        }
    }

    private void setResult(final RestfulResult baseResponse,final ScenarioCodeEnum scenarioCodeEnum, final boolean isIdempotent){
        baseResponse.setSuccess(RestfulCodeEnum.SUCCESS.getCode().equals(baseResponse.getCode()));

        if(isIdempotent){
            final ErrorContext errorContext = new ErrorContext(
                    CommonConstant.PRODUCTION_AND_APP_CODE , scenarioCodeEnum.getCode(), ApplicationErrorTypeEnum.BIZ_INVALID_ERROR.getCode() + ErrorCodeEnum.ERROR_IDEMPOTENCY.getCode(),ErrorCodeEnum.ERROR_IDEMPOTENCY.getDesc());
            baseResponse.setErrorCtx(errorContext);
        }
    }


    private void setupFailedResult(final BaseResponse baseResponse, final ScenarioCodeEnum scenarioCodeEnum, final BizException be, final String customErrorMsg ){
        if(be!=null){
            ResponseUtil.buildFailedResponse(baseResponse, scenarioCodeEnum, be.getErrorCodeEnum(),customErrorMsg);
        }else {
            ResponseUtil.buildFailedResponse(baseResponse,scenarioCodeEnum, ErrorCodeEnum.COMMON_INNER_ERROR,customErrorMsg);
        }
    }

    private void setupFailedResult(final RestfulResult baseResponse, final ScenarioCodeEnum scenarioCodeEnum, final BizException be, final String customErrorMsg ){
        if(be!=null){
            ResponseUtil.buildFailedResponse(baseResponse, scenarioCodeEnum, be.getErrorCodeEnum(),customErrorMsg);
        }else {
            ResponseUtil.buildFailedResponse(baseResponse,scenarioCodeEnum, ErrorCodeEnum.COMMON_INNER_ERROR,customErrorMsg);
        }
    }


}
